﻿/****************************************************************************************************
	Copyright (C) 2010 RapidWebDev Organization (http://rapidwebdev.org)
	Author: Eunge, Legal Name: Jian Liu, Email: eunge.liu@RapidWebDev.org

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 2 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
 ****************************************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using BaoJianSoft.Common;
using BaoJianSoft.Common.Data;

namespace BaoJianSoft.Platform.Linq
{
	/// <summary>
	/// Based on Linq's Membership APIs's extension method
	/// </summary>
	public static class MembershipExtensions
	{
		/// <summary>
		/// Find organization business objects by predicates.
		/// </summary>
		/// <param name="organizationApi">extension method to organization api.</param>
		/// <param name="predicate">predicate in linq expression</param>
		/// <param name="dynamicPredicate">dynamic predicate in string format</param>
		/// <param name="orderby">dynamic orderby command</param>
		/// <param name="pageIndex">current paging index</param>
		/// <param name="pageSize">page size</param>
		/// <param name="recordCount">total hit records count</param>
		/// <param name="parameters">parameters to dynamic predicate</param>
		/// <returns>Returns enumerable organizations</returns>
		public static IEnumerable<OrganizationObject> FindOrganizations(this IOrganizationApi organizationApi, Expression<Func<Organization, bool>> predicate, string dynamicPredicate, string orderby, int pageIndex, int pageSize, out int recordCount, params object[] parameters)
		{
			try
			{
				MembershipDataContext ctx = DataContextFactory.Create<MembershipDataContext>();

				IAuthenticationContext authenticationContext = SpringContext.Current.GetObject<IAuthenticationContext>();
				var q = from org in ctx.Organizations where org.ApplicationId == authenticationContext.ApplicationId select org;
				if (predicate != null)
					q = q.Where(predicate);

				if (!Kit.IsEmpty(dynamicPredicate))
					q = q.Where(dynamicPredicate, parameters);

				if (!Kit.IsEmpty(orderby))
					q = q.OrderBy(orderby);

				recordCount = q.Count();
				IEnumerable<Guid> organizationIds = q.Skip(pageIndex * pageSize).Take(pageSize).Select(org => org.OrganizationId);
				return organizationApi.BulkGetOrganizations(organizationIds).Values;
			}
			catch (Exception exp)
			{
				Logger.Instance(organizationApi).Error(exp);
				throw;
			}
		}

		/// <summary>
		/// Find role objects by predicates.
		/// </summary>
		/// <param name="membershipApi">extension method to role api.</param>
		/// <param name="predicate">predicate in linq expression</param>
		/// <param name="dynamicPredicate">dynamic predicate in string format</param>
		/// <param name="orderby">dynamic orderby command</param>
		/// <param name="pageIndex">current paging index</param>
		/// <param name="pageSize">page size</param>
		/// <param name="recordCount">total hit records count</param>
		/// <param name="parameters">parameters to dynamic predicate</param>
		/// <returns>Returns enumerable role objects</returns>
		public static IEnumerable<RoleObject> FindRoles(this IRoleApi roleApi, Expression<Func<Role, bool>> predicate, string dynamicPredicate, string orderby, int pageIndex, int pageSize, out int recordCount, params object[] parameters)
		{
			try
			{
				MembershipDataContext ctx = DataContextFactory.Create<MembershipDataContext>();

				IAuthenticationContext authenticationContext = SpringContext.Current.GetObject<IAuthenticationContext>();
				var q = from r in ctx.Roles where r.ApplicationId == authenticationContext.ApplicationId select r;
				if (predicate != null)
					q = q.Where(predicate);

				if (!Kit.IsEmpty(dynamicPredicate))
					q = q.Where(dynamicPredicate, parameters);

				if (!Kit.IsEmpty(orderby))
					q = q.OrderBy(orderby);

				recordCount = q.Count();
				IEnumerable<Guid> roleIds = q.Skip(pageIndex * pageSize).Take(pageSize).Select(r => r.RoleId);
				return roleApi.BulkGet(roleIds).Values;
			}
			catch (Exception exp)
			{
				Logger.Instance(roleApi).Error(exp);
				throw;
			}
		}

		/// <summary>
		/// Find user business objects by predicates.
		/// </summary>
		/// <param name="membershipApi">extension method to membership api.</param>
		/// <param name="predicate">predicate in linq expression</param>
		/// <param name="dynamicPredicate">dynamic predicate in string format</param>
		/// <param name="orderby">dynamic orderby command</param>
		/// <param name="pageIndex">current paging index</param>
		/// <param name="pageSize">page size</param>
		/// <param name="recordCount">total hit records count</param>
		/// <param name="parameters">parameters to dynamic predicate</param>
		/// <returns>Returns enumerable user objects</returns>
		public static IEnumerable<UserObject> FindUsers(this IMembershipApi membershipApi, Expression<Func<User, bool>> predicate, string dynamicPredicate, string orderby, int pageIndex, int pageSize, out int recordCount, params object[] parameters)
		{
			try
			{
				MembershipDataContext ctx = DataContextFactory.Create<MembershipDataContext>();

				IAuthenticationContext authenticationContext = SpringContext.Current.GetObject<IAuthenticationContext>();
				var q = from user in ctx.Users where user.ApplicationId == authenticationContext.ApplicationId select user;
				if (predicate != null)
					q = q.Where(predicate);

				if (!Kit.IsEmpty(dynamicPredicate))
					q = q.Where(dynamicPredicate, parameters);

				if (!Kit.IsEmpty(orderby))
					q = q.OrderBy(orderby);

				recordCount = q.Count();
				IEnumerable<Guid> userIds = q.Skip(pageIndex * pageSize).Take(pageSize).Select(user => user.UserId);
				return membershipApi.BulkGet(userIds).Values;
			}
			catch (Exception exp)
			{
				Logger.Instance(membershipApi).Error(exp);
				throw;
			}
		}

		/// <summary>
		/// Find concrete data by nature linq expression.
		/// </summary>
		/// <param name="concreteDataApi"></param>
		/// <param name="category"></param>
		/// <param name="predicate"></param>
		/// <param name="dynamicPredicate"></param>
		/// <param name="orderby"></param>
		/// <param name="pageIndex"></param>
		/// <param name="pageSize"></param>
		/// <param name="recordCount"></param>
		/// <param name="parameters"></param>
		/// <returns></returns>
		public static IEnumerable<ConcreteDataObject> FindConcreteData(this IConcreteDataApi concreteDataApi, string category, Expression<Func<ConcreteDataObject, bool>> predicate, string dynamicPredicate, string orderby, int pageIndex, int pageSize, out int recordCount, params object[] parameters)
		{
			Kit.NotNull(category, "category");

			try
			{
				var q = concreteDataApi.FindAllByType(category).AsQueryable();
				if (predicate != null)
					q = q.Where(predicate);

				if (!Kit.IsEmpty(dynamicPredicate))
					q = q.Where(dynamicPredicate, parameters);

				if (!Kit.IsEmpty(orderby))
					q = q.OrderBy(orderby);

				recordCount = q.Count();
				return q.Skip(pageIndex * pageSize).Take(pageSize);
			}
			catch (Exception exp)
			{
				Logger.Instance(concreteDataApi).Error(exp);
				throw;
			}
		}

		/// <summary>
		/// Find hierarchy data by nature linq expression.
		/// </summary>
		/// <param name="hierarchyApi"></param>
		/// <param name="hierarchyType"></param>
		/// <param name="predicate"></param>
		/// <param name="dynamicPredicate"></param>
		/// <param name="orderby"></param>
		/// <param name="pageIndex"></param>
		/// <param name="pageSize"></param>
		/// <param name="recordCount"></param>
		/// <param name="parameters"></param>
		/// <returns></returns>
		public static IEnumerable<HierarchyDataObject> FindHierarchyData(this IHierarchyApi hierarchyApi, string hierarchyType, Expression<Func<HierarchyDataObject, bool>> predicate, string dynamicPredicate, string orderby, int pageIndex, int pageSize, out int recordCount, params object[] parameters)
		{
			try
			{
				IQueryable<HierarchyDataObject> q = hierarchyApi.GetAllHierarchyData(hierarchyType).AsQueryable();

				if (predicate != null)
					q = q.Where(predicate);

				if (!Kit.IsEmpty(dynamicPredicate))
					q = q.Where(dynamicPredicate, parameters);

				if (!Kit.IsEmpty(orderby))
					q = q.OrderBy(orderby);

				recordCount = q.Count();
				return q.Skip(pageIndex * pageSize).Take(pageSize);
			}
			catch (Exception exp)
			{
				Logger.Instance(hierarchyApi).Error(exp);
				throw;
			}
		}
	}
}

